#include <stdlib.h>
#include <dequeue.h>

int dequeue_is_empty(dequeue*);

dequeue *new_dequeue()
{
    dequeue *dequeue = malloc(sizeof(dequeue));

    dequeue->length = 0;
    dequeue->head = NULL;
    dequeue->tail = NULL;

    return dequeue;
}

dequeue_node *new_dequeue_node(void *data)
{
    dequeue_node *new_node = malloc(sizeof(dequeue_node));

    new_node->data = data;
    new_node->next = NULL;
    new_node->prev = NULL;

    return new_node;
}

void dequeue_push_head(dequeue *dequeue, void *data)
{
    dequeue_node *new_node = new_dequeue_node(data);

    if(!dequeue_is_empty(dequeue))
    {
        new_node->next = dequeue->head;
        dequeue->head->prev = new_node;

        dequeue->head = new_node;
    } else {
        dequeue->tail = dequeue->head = new_node;
    }

    dequeue->length++;
}

void *dequeue_pop_head(dequeue *dequeue)
{
    void *popped_data = NULL;

    if(!dequeue_is_empty(dequeue))
    {
        popped_data = dequeue->head->data;

        free(&(dequeue->head));
        dequeue->head = dequeue->head->next;

        if(dequeue->head == NULL)
        {
            dequeue->tail = NULL;
        }
        else
        {
            dequeue->head->prev = NULL;
        }

        dequeue->length--;
    }

    return popped_data;
}

void dequeue_push_tail(dequeue *dequeue, void *data)
{
    dequeue_node *new_node = new_dequeue_node(data);

    new_node->prev = dequeue->tail;

    if(dequeue->head == NULL)
    {
        dequeue->head = new_node;
    }
    else
    {
        dequeue->tail->next = new_node;
    }

    dequeue->tail = new_node;

    dequeue->length++;
}

void *dequeue_pop_tail(dequeue *dequeue)
{
    void *popped_data = NULL;

    if(!dequeue_is_empty(dequeue))
    {
        popped_data = dequeue->tail->data;

        free(&(dequeue->tail));
        dequeue->tail = dequeue->tail->prev;

        if(dequeue->tail == NULL)
        {
            dequeue->head = NULL;
        }
        else
        {
            dequeue->tail->next = NULL;
        }

        dequeue->length--;
    }

    return popped_data;
}

int dequeue_is_empty(dequeue *dequeue)
{
    return dequeue->length == 0;
}
